package main

import (
	"fmt"
	"github.com/pkg/sftp"
	"golang.org/x/crypto/ssh"
	"gopkg.in/ini.v1"
	"io"
	"log"
	"os"
	"strconv"
	"strings"
	"time"
)

func fileGet(sftpSession *sftp.Client, localFilePath string, remoteFilePath string) {

	// 打开本地文件
	localFile, err := os.Create(localFilePath)
	if err != nil {
		log.Fatalf("Failed to open local file: %v", err)
	}
	defer func(localFile *os.File) {
		err := localFile.Close()
		if err != nil {
			log.Fatalf("Failed to close local file: %v", err)
		}
	}(localFile)

	// 在远程创建文件并写入
	remoteFile, err := sftpSession.Open(remoteFilePath)
	if err != nil {
		log.Fatalf("Failed to create remote file: %v", err)
	}
	defer func(remoteFile *sftp.File) {
		err := remoteFile.Close()
		if err != nil {
			log.Fatalf("Failed to close remote file: %v", err)
		}
	}(remoteFile)

	// 执行文件复制
	_, err = io.Copy(localFile, remoteFile)
	if err != nil {
		log.Fatalf("Failed to copy file: %v", err)
	}

	// 确保文件内容被写入磁盘
	err = localFile.Sync()

	if err != nil {

		log.Fatalf("Failed to sync file: %v", err)

	}

	if err == nil {

		fmt.Println(localFilePath)

	}

	fmt.Println("File transferred %s successfully.", localFilePath)

}

func getFileFromRemote() {

	cfg, err := ini.Load("config.ini")

	if err != nil {
		fmt.Println("配置文件读取错误，请检查文件路径:", err)
	}

	for i := 2; i < len(cfg.Sections()); i++ {

		username := cfg.Sections()[i].Key("username").Value()

		password := cfg.Sections()[i].Key("password").Value()

		remoteIP := cfg.Sections()[i].Key("remote_ip").Value()

		remotePort := cfg.Sections()[i].Key("remote_port").Value()

		local_path := cfg.Sections()[i].Key("local_path").Value()

		remote_path := cfg.Sections()[i].Key("remote_path").Value()

		fileFilte := cfg.Sections()[i].Key("fileFilte").Value()

		config := &ssh.ClientConfig{
			User: username,
			Auth: []ssh.AuthMethod{
				ssh.Password(password), // 或者使用 ssh.PublicKeys
			},
			HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 注意：在生产环境中，你应该验证主机密钥
		}

		client, err := ssh.Dial("tcp", remoteIP+":"+remotePort, config)

		if err != nil {

			log.Fatalf("Failed to dial: %s", err)
		}

		sftpSession, err := sftp.NewClient(client)

		if err != nil {
			log.Fatalf("Unable to establish SFTP session: %s", err)
		}

		defer sftpSession.Close()

		// 创建一个新的SSH会话
		session, err := client.NewSession()
		if err != nil {
			log.Fatalf("Failed to create session: %s", err)
		}
		defer session.Close()

		dir, err := sftpSession.Open(remote_path)

		if err != nil {

			log.Fatalf("Failed to open remote file: %s", err)

		}

		defer dir.Close()

		w := sftpSession.Walk(remote_path)

		for w.Step() {

			if w.Err() != nil || w.Stat().IsDir() {

				continue

			}

			fmt.Println(w.Stat().Name())

			remoteFile_path := w.Path()

			localFile_path := local_path + "/" + w.Stat().Name()

			if strings.Contains(w.Stat().Name(), fileFilte) {
				fileGet(sftpSession, localFile_path, remoteFile_path)

				sftpSession.Remove(remoteFile_path)

			}

		}

	}

}

func main() {

	cfg, err := ini.Load("config.ini")

	if err != nil {
		fmt.Println("配置文件读取错误，请检查文件路径:", err)
	}

	timeSecond := cfg.Section("uploadCron").Key("uploadFileSecond").Value()

	num, err := strconv.Atoi(timeSecond)

	if err != nil {
		// 如果转换失败，处理错误
		fmt.Println("转换失败:", err)
		return
	}

	// 定义任务触发间隔
	interval := time.Duration(num) * time.Second

	// 使用一个无限循环来定时触发任务
	for {
		// 执行定时任务
		getFileFromRemote()

		// 等待指定的时间间隔
		time.Sleep(interval)
	}

}
